package server;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.*;
import util.*;



public class ServerSocketThread extends SocketThread {

	public static final int STATE_PRE_CONNECT = 0; // Nothing have happened yet.
	public static final int STATE_CONNECTED = 1;   // Socket is open. Server sends info and goes to next state.
	public static final int STATE_LOGGING_IN = 2;  // Client should send username.
	public static final int STATE_LOGGED_IN = 3;   // User is logged in. Game can now commence. 
	
	private int state = STATE_PRE_CONNECT;
	private String username;
	
	public ServerSocketThread(Socket playerSocket) throws UnsupportedEncodingException, IOException{
		super(playerSocket);
		
	}
	
	public void run() {
		try {
			
			Server.consolePrint("New connection from " + socket.getInetAddress().getHostAddress() + 
									   " (" + socket.getInetAddress().getHostName() + ")");
			socket.setKeepAlive(true);
			state = STATE_CONNECTED;
			
			// Now provide the current game info, and a list of usernames already taken
			out.println(Game.gameInfo());
			out.flush();
			
			state = STATE_LOGGING_IN;
			
			try {
				String inputLine;
				while ((inputLine = in.readLine()) != null){
					// The reader will return null when connection is lost
					processClientInput(inputLine);
					yield();
				}
			} catch (IOException e) {
					// Connection reset
					Server.consolePrint("Connection closed for username: " + (username != null ? username:"null") );
			} finally {
				Server.consolePrint("SocketThread finally clause");
				if (!socket.isClosed())
					close();
			}
			
		} catch (IOException e) {
			// 
			Server.consolePrint("Lost connection to " + username != null ? username : "non-auth user");
			e.printStackTrace();
		}
	}
	
	public String getUsername() {
		if (username != null)
			return new String(username);
		
		return "";
	}
	
	public void close() {
		Server.consolePrint("SocketThread.close()");
		try {
			socket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		Server.removeConnection(this);
	}
	
	private synchronized void processClientInput(String str){
		if (str != null){
			
			switch (state) {
			
				// There should not be any input from the client before this state	
				case STATE_LOGGING_IN:
					// Confirm that the server acknowledges the username
					if (!str.contains(" ")){
						int result = Game.canAddUser(str);
						
						if (result < 0){ // Too many connected players
							state = STATE_PRE_CONNECT; // doesn't really matter, as the connection will now be closed.
							out.println("Too many connected players. Try again later.");
							out.flush();
							close();
							
						} else if (result == 0){ // Username taken
							state = STATE_CONNECTED;
							out.println("Username already taken. Try a new.");
							out.flush();
							
						} else { // All went fine
							Server.consolePrint(str + " logged in from " + socket.getInetAddress().getHostAddress());
							state = STATE_LOGGED_IN;
							out.println("welcome "+str);
							out.flush();
							username = str;
							Game.addUser(str, this);
						}
					}
					break;
					
				case STATE_LOGGED_IN:
					// Print everything. This contains game-info from server.
					if (str.equalsIgnoreCase("exit")) {
						close();
					} else {
						Game.processPlayerAnswer(username, str);
					}
					break;
			}
			
		}
	}
	
	
}
